package com.zhr.tools.compile;

import org.eclipse.jdt.internal.compiler.batch.Main;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;


/**
 * 编译Java代码(pojo)并返回Class
 *
 * @author zhr
 */
public class EcjTool {
    /**
     * 将 java Class 字符串生成文件 并存放在指定目录
     *
     * @param javaCode  java 代码
     * @param directory 存放目录
     * @return .java文件绝对路径
     * @throws IOException \
     */
    private static String getFilePath(String javaCode, String directory) throws IOException {
        String className = getClassName(javaCode);
        File tempFile = new File(directory, className + ".java");
        FileWriter fileWriter = new FileWriter(tempFile);
        fileWriter.write(javaCode);
        fileWriter.flush();
        fileWriter.close();
        return tempFile.getAbsolutePath();
    }

    /**
     * 根据Java代码 获取class 类名
     *
     * @param javaCode Java 代码
     * @return class名称
     */
    private static String getClassName(String javaCode) {
        int start = javaCode.indexOf("class") + 5;
        int end = javaCode.indexOf("{");
        return javaCode.substring(start, end).trim();
    }

    /**
     * 使用ECJ编译Java代码
     *
     * @param javaFile Java文件
     * @param dstPath  生成的.class 文件路径
     * @return 编译结果
     */
    private static boolean ecjCompile(String javaFile, String dstPath) {
        Main ecjCompiler = new Main(new PrintWriter(System.out), new PrintWriter(System.err),
                false, null, null);
        String[] argv = {"-1.8", "-encoding", "utf-8", javaFile, "-d", dstPath};
        return ecjCompiler.compile(argv);
    }

    /**
     * 创建目录
     *
     * @param dirPath 目录
     * @param info    报错信息
     */
    private static void mkdir(String dirPath, String info) {
        File javaClassFile = new File(dirPath);
        if (!javaClassFile.exists()) {
            boolean success = javaClassFile.mkdirs();
            if (!success) {
                System.out.println(info);
            }
        }
    }

    /**
     * 编译Java代码并返回Class
     *
     * @param javaCode Java代码
     * @param tempDir  临时目录
     * @return Class
     * @throws IOException \
     */
    public static Class compileJavaCode(String javaCode, String tempDir) throws IOException {
        //获取临时目录
        if (tempDir == null || "".equals(tempDir.trim())) {
            tempDir = System.getProperty("java.io.tmpdir");
        }
        //创建临时Java文件目录
        String javaFileDirPath = tempDir + File.separator + "java" + File.separator;
        mkdir(javaFileDirPath, "make java dir file");
        //创建临时class文件目录
        String javaClassPath = tempDir + File.separator + "class" + File.separator;
        mkdir(javaClassPath, "make class dir file");
        //生成Java文件 并获取绝对路径
        String javaFilePath = getFilePath(javaCode, javaFileDirPath);
        //根据Java代码获取类名
        String className = getClassName(javaCode);
        //调用ecj进行编译
        boolean b = ecjCompile(javaFilePath, javaClassPath);
        if (b) {
            System.out.println("compile success");
        }
        //使用自定义的ClassLoader加载Class文件
        MyClassLoader loader = new MyClassLoader();
        String classPath = javaClassPath + File.separator + className + ".class";
        //加载并返回Class
        return loader.findClass(classPath);
    }
}
